package com.peas.platform.common.core.enums;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;

import java.util.*;

public interface BaseEnum {

	static <E extends BaseEnum> boolean isKeyExists(Class<E> enumClass, String key) {
		if (StrUtil.isEmpty(key)) {
			return false;
		}
		List<String> keys = getKeyList(enumClass);
		if (CollUtil.isEmpty(keys)) {
			return false;
		}
		return keys.contains(key);
	}

	static <E extends BaseEnum> boolean isValueExists(Class<E> enumClass, String value) {
		if (StrUtil.isEmpty(value)) {
			return false;
		}
		List<String> values = getValueList(enumClass);
		if (CollUtil.isEmpty(values)) {
			return false;
		}
		return values.contains(value);
	}

	static <E extends BaseEnum> List<String> getKeyList(Class<E> enumClass) {
		List<String> list = new ArrayList<>();
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return list;
		}
		for (E e : enumClass.getEnumConstants()) {
			list.add(e.getKey());
		}
		return list;
	}

	static <E extends BaseEnum> List<String> getKeyList(Class<E> enumClass, List<E> enums) {
		if (CollUtil.isEmpty(enums)) {
			return Collections.emptyList();
		}
		List<String> result = new ArrayList<>();
		for (E e : enums) {
			result.add(e.getKey());
		}
		return result;
	}

	static <E extends BaseEnum> List<String> getValueList(Class<E> enumClass) {
		List<String> list = new ArrayList<>();
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return list;
		}
		for (E e : enumClass.getEnumConstants()) {
			list.add(e.getValue());
		}
		return list;
	}

	static <E extends BaseEnum> List<String> getValueList(Class<E> enumClass, List<E> enums) {
		if (CollUtil.isEmpty(enums)) {
			return Collections.emptyList();
		}
		List<String> result = new ArrayList<>();
		for (E e : enums) {
			result.add(e.getValue());
		}
		return result;
	}

	static <E extends BaseEnum> List<Map<String, String>> getMapList(Class<E> enumClass) {
		List<Map<String, String>> mapList = new ArrayList<>();
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return mapList;
		}
		for (E e : enumClass.getEnumConstants()) {
			Map<String, String> map = new HashMap<>();
			map.put("key", e.getKey());
			map.put("value", e.getValue());
			map.put("elTagType", e.getElTagType().getKey());
			map.put("elTagClass", e.getElTagClass());
			map.put("elTagStyle", e.getElTagStyle());
			mapList.add(map);
		}
		return mapList;
	}

	@SafeVarargs
	static <E extends BaseEnum> List<Map<String, String>> getMapList(E ... enumData) {
		List<Map<String, String>> mapList = new ArrayList<>();
		for (BaseEnum ed : enumData) {
			Map<String, String> map = new HashMap<>();
			map.put("key", ed.getKey());
			map.put("value", ed.getValue());
			map.put("elTagType", ed.getElTagType().getKey());
			map.put("elTagClass", ed.getElTagClass());
			map.put("elTagStyle", ed.getElTagStyle());
			mapList.add(map);
		}
		return mapList;
	}

	static <E extends BaseEnum> Map<String, String> getMap(E enumData) {
		Map<String, String> enumMap = new HashMap<>();
		enumMap.put("key", enumData.getKey());
		enumMap.put("value", enumData.getValue());
		enumMap.put("elTagType", enumData.getElTagType().getKey());
		enumMap.put("elTagClass", enumData.getElTagClass());
		enumMap.put("elTagStyle", enumData.getElTagStyle());
		return enumMap;
	}

	static <E extends BaseEnum> String key2Value(Class<E> enumClass, String key) {
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return "";
		}
		if (StrUtil.isBlank(key)) {
			return null;
		}
		for (E e : enumClass.getEnumConstants()) {
			if (StrUtil.equals(e.getKey(), key)) {
				return e.getValue();
			}
		}
		return "";
	}

	static <E extends BaseEnum> List<String> key2Value(Class<E> enumClass, List<String> keys) {
		if (CollUtil.isEmpty(keys)) {
			return new ArrayList<>();
		}
		List<String> values = new ArrayList<>();
		for (String key : keys) {
			values.add(key2Value(enumClass, key));
		}
		return values;
	}

	static <E extends BaseEnum> E key2Enum(Class<E> enumClass, String key) {
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return null;
		}
		if (StrUtil.isBlank(key)) {
			return null;
		}
		for (E e : enumClass.getEnumConstants()) {
			if (StrUtil.equals(e.getKey(), key)) {
				return e;
			}
		}
		return null;
	}

	static <E extends BaseEnum> List<E> key2Enum(Class<E> enumClass, List<String> keys) {
		if (CollUtil.isEmpty(keys)) {
			return new ArrayList<>();
		}
		List<E> enums = new ArrayList<>();
		for (String key : keys) {
			enums.add(key2Enum(enumClass, key));
		}
		return enums;
	}

	static <E extends BaseEnum> String value2Key(Class<E> enumClass, String value) {
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return "";
		}
		if (StrUtil.isBlank(value)) {
			return null;
		}
		for (E e : enumClass.getEnumConstants()) {
			if (StrUtil.equals(e.getValue(), value)) {
				return e.getKey();
			}
		}
		return "";
	}

	static <E extends BaseEnum> List<String> value2Key(Class<E> enumClass, List<String> values) {
		if (CollUtil.isEmpty(values)) {
			return new ArrayList<>();
		}
		List<String> keys = new ArrayList<>();
		for (String value : values) {
			keys.add(value2Key(enumClass, value));
		}
		return keys;
	}

	static <E extends BaseEnum> E value2Enum(Class<E> enumClass, String value) {
		if (!BaseEnum.class.isAssignableFrom(enumClass)) {
			return null;
		}
		if (StrUtil.isBlank(value)) {
			return null;
		}
		for (E e : enumClass.getEnumConstants()) {
			if (StrUtil.equals(e.getValue(), value)) {
				return e;
			}
		}
		return null;
	}

	static <E extends BaseEnum> List<E> value2Enum(Class<E> enumClass, List<String> values) {
		if (CollUtil.isEmpty(values)) {
			return new ArrayList<>();
		}
		List<E> enums = new ArrayList<>();
		for (String value : values) {
			enums.add(value2Enum(enumClass, value));
		}
		return enums;
	}

	static <E extends BaseEnum> String getKeyIfNotNull(E enumObj) {
		return enumObj == null ? null : enumObj.getKey();
	}

	static <E extends BaseEnum> String getValueIfNotNull(E enumObj) {
		return enumObj == null ? null : enumObj.getValue();
	}

	String getKey();

	String getValue();

	default CommonElType getElTagType() {
		return CommonElType.info;
	}

	default String getElTagClass() {
		return CharSequenceUtil.EMPTY;
	}

	default String getElTagStyle() {
		return CharSequenceUtil.EMPTY;
	}

	default String comment() {
		return this.getClass().getName();
	}

}
